#pragma once
#include <deque>
#include <assert.h>
#include "Condition_WIN.h"

template<typename T>
class BlockingQueue {
public:
    BlockingQueue()
        : mutex_(CreateMutex(NULL, FALSE, NULL)),
        cond_(mutex_),
        queue_() {
    }

    void put(const T& x) {
        MutexLockGuard lock(mutex_);
        queue_.push_back(x);
        cond_.Notify();
    }

    T take() {
        MutexLockGuard lock(mutex_);
        while (queue_.empty()) {
            cond_.Wait();
        }
        assert(!queue_.empty());
        T front(queue_.front());
        queue_.pop_front();
        return front;
    }

    size_t size() const {
        MutexLockGuard lock(mutex_);
        return queue_.size();
    }

private:
    mutable HANDLE mutex_;
    Condition cond_;
    std::deque<T> queue_;
};
